package com.jzlin.funhub.framework.utils;

import cn.hutool.core.util.StrUtil;
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class DynamicParamParser {
    static LocalVariableTableParameterNameDiscoverer parameterNameDiscoverer = new LocalVariableTableParameterNameDiscoverer();
    private static final String PREFIX = "${";
    private static final String SUFFIX = "}";
    private static final Pattern regex = Pattern.compile("\\$\\{([^}]*)\\}");

    public DynamicParamParser() {
    }

    private static boolean isBaseType(Class className, boolean isBaseStr) {
        if (isBaseStr && className.equals(String.class)) {
            return true;
        } else {
            return className.equals(Integer.class) || className.equals(Integer.TYPE) || className.equals(Byte.class) || className.equals(Byte.TYPE) || className.equals(Long.class) || className.equals(Long.TYPE) || className.equals(Double.class) || className.equals(Double.TYPE) || className.equals(Float.class) || className.equals(Float.TYPE) || className.equals(Character.class) || className.equals(Character.TYPE) || className.equals(Short.class) || className.equals(Short.TYPE) || className.equals(Boolean.class) || className.equals(Boolean.TYPE);
        }
    }

    public static boolean isDynameicParam(String var) {
        return var.contains("${");
    }

    public static String handle(Method method, Object[] args, String var) {
        if (method != null && args != null && !StrUtil.isBlank(var)) {
            if (!isDynameicParam(var)) {
                return var;
            } else {
                Matcher matcher = regex.matcher(var);
                List<String> varList = new ArrayList();
                List<Object> valList = new ArrayList();

                while(matcher.find()) {
                    varList.add(matcher.group(1));
                }

                Iterator var6 = varList.iterator();

                String v;
                while(var6.hasNext()) {
                    v = (String)var6.next();
                    Object o = parserVar(method, args, v);
                    if (o == null) {
                        valList.add(v);
                    } else {
                        valList.add(o);
                    }
                }

                String pattern = var.replaceAll(regex.toString(), "%s");
                v = String.format(pattern, valList.toArray());
                return v;
            }
        } else {
            return "";
        }
    }

    private static Object parserVar(Method method, Object[] objects, String var) {
        Class[] parameterTypes = method.getParameterTypes();
        String[] parameterNames = parameterNameDiscoverer.getParameterNames(method);
        Object parsredVar = null;

        for(int i = 0; i < parameterTypes.length; ++i) {
            Class clazz = parameterTypes[i];
            if (isBaseType(clazz, true)) {
                String paraName = parameterNames[i];
                if (paraName.equals(var)) {
                    parsredVar = objects[i];
                    if (parsredVar != null) {
                        break;
                    }
                }
            } else {
                parsredVar = handerCustomerObj(objects[i], var);
                if (parsredVar != null) {
                    break;
                }
            }
        }

        return parsredVar;
    }

    private static Object handerCustomerObj(Object customerObj, String var) {
        Object val = null;
        Field[] declaredFields = customerObj.getClass().getDeclaredFields();
        Field[] var4 = declaredFields;
        int var5 = declaredFields.length;

        for(int var6 = 0; var6 < var5; ++var6) {
            Field field = var4[var6];
            if (field.getName().equals(var)) {
                field.setAccessible(true);

                try {
                    val = field.get(customerObj);
                    break;
                } catch (Exception var9) {
                    var9.printStackTrace();
                }
            }
        }

        return val;
    }
}
